<?php
namespace app\common\job;

use app\common\model\DistrictModel;
use app\common\model\EsModel;
use Exception;
use think\facade\Log;
use think\queue\Job;

class EsJob
{
    /**
     * 添加 es 数据
     * @author 贺强
     * @time   2022/6/22 15:52
     * @param Job $job 当前任务
     * @param array $data 要添加到 es 数据
     * @return bool
     */
    public function add_es(Job $job, array $data) : bool
    {
        if (empty($data['index']) || empty($data['data'])) {
            $job->delete();
            return false;
        }
        try {
            $res = EsModel::add($data['index'], $data['data']);
            if ($res) {
                $job->delete();
                return true;
            } elseif ($job->attempts() > 10) {
                $job->delete();
                $error = ['jobName' => $job->getName(), 'data' => $data];
                throw new Exception('执行次数超限:' . json_encode($error));
            } else {
                $job->release();
                return false;
            }
        } catch (Exception $e) {
            $job->delete();
            Log::error($e->getMessage());
            return false;
        }
    }

    /**
     * 批量保存 es 数据
     * @author 贺强
     * @time   2022/6/22 15:52
     * @param Job $job 当前任务
     * @param array $data 要保存到 es 数据
     * @return bool
     */
    public function save_es(Job $job, array $data) : bool
    {
        if (empty($data)) {
            $job->delete();
            return false;
        }
        try {
            $res = EsModel::saveArr($data);
            if ($res) {
                $job->delete();
                return true;
            } elseif ($job->attempts() > 10) {
                $job->delete();
                $error = ['jobName' => $job->getName(), 'data' => $data];
                throw new Exception('执行次数超限:' . json_encode($error));
            } else {
                $job->release();
                return false;
            }
        } catch (Exception $e) {
            $job->delete();
            Log::error($e->getMessage());
            return false;
        }
    }

    /**
     * 删除 es 数据
     * @author 贺强
     * @time   2022/6/22 16:12
     * @param Job $job 当前任务
     * @param array $data 删除数据
     * @return bool
     */
    public function del_es(Job $job, array $data) : bool
    {
        if (empty($data['index']) || empty($data['id'])) {
            $job->delete();
            return false;
        }
        try {
            $res = EsModel::delFile($data['index'], $data['id']);
            if ($res) {
                $job->delete();
                return true;
            } elseif ($job->attempts() > 10) {
                $job->delete();
                $error = ['jobName' => $job->getName(), 'data' => $data];
                throw new Exception('执行次数超限:' . json_encode($error));
            } else {
                $job->release();
                return false;
            }
        } catch (Exception $e) {
            $job->delete();
            Log::error($e->getMessage());
            return false;
        }
    }

    /**
     * 修改 es 数据
     * @author 贺强
     * @time   2022/6/22 16:20
     * @param Job $job 当前任务
     * @param array $data 修改的数据
     * @return bool
     */
    public function modify_es(Job $job, array $data) : bool
    {
        if (empty($data['index']) || empty($data['data'])) {
            $job->delete();
            return false;
        }
        try {
            $res = EsModel::modifyField($data['index'], $data['data']);
            if ($res) {
                $job->delete();
                return true;
            } elseif ($job->attempts() > 10) {
                $job->delete();
                $error = ['jobName' => $job->getName(), 'data' => $data];
                throw new Exception('执行次数超限:' . json_encode($error));
            } else {
                $job->release();
                return false;
            }
        } catch (Exception $e) {
            $job->delete();
            Log::error($e->getMessage());
            return false;
        }
    }

    /**
     * 同步数据库表数据到 es
     * @author 贺强
     * @time   2022/8/25 11:29
     * @param Job $job 当前任务
     * @param array $data 同步参数
     * @return bool
     */
    public function sync_data(Job $job, array $data) : bool
    {
        if (empty($data['table']) || empty($data['sql'])) {
            $job->delete();
            return false;
        }
        try {
            $res = EsModel::syncData($data);
            if ($res) {
                $job->delete();
                return true;
            } elseif ($job->attempts() > 10) {
                $job->delete();
                $error = ['jobName' => $job->getName(), 'data' => $data];
                throw new Exception('执行次数超限:' . json_encode($error));
            } else {
                $job->release();
                return false;
            }
        } catch (Exception $e) {
            $job->delete();
            Log::error($e->getMessage());
            return false;
        }
    }

    /**
     * 同步数据库表数据到 es
     * @author 贺强
     * @time   2023/8/23 10:22
     * @param Job $job 当前任务
     * @param array $data 同步参数
     * @return bool
     */
    public function sync_attr_data(Job $job, array $data) : bool
    {
        if (empty($data['table']) || empty($data['ids']) || empty($data['attr_field']) || empty($data['field'])) {
            $job->delete();
            return false;
        }
        try {
            $res = EsModel::syncAttrData($data);
            if ($res) {
                $job->delete();
                return true;
            } elseif ($job->attempts() > 10) {
                $job->delete();
                $error = ['jobName' => $job->getName(), 'data' => $data];
                throw new Exception('执行次数超限:' . json_encode($error));
            } else {
                $job->release();
                return false;
            }
        } catch (Exception $e) {
            $job->delete();
            Log::error($e->getMessage());
            return false;
        }
    }

    /**
     * 重刷区划
     * @author 贺强
     * @time   2023/4/20 14:45
     * @param Job $job 当前任务
     * @param string $code 区划码
     * @return bool
     */
    public function refresh_district(Job $job, string $code = '') : bool
    {
        if (empty($code)) {
            $job->delete();
            return false;
        }
        try {
            // 当前区划是否存在
            $district = DistrictModel::getModel(['code' => $code], true, '', 0);
            if (empty($district)) {
                $job->delete();
                $error = ['jobName' => $job->getName(), 'code' => $code];
                throw new Exception('区划不存在:' . json_encode($error));
            }
            $res = $this->refresh_sub_item($district);
            if ($res === true) {
                $job->delete();
                return true;
            } elseif ($job->attempts() > 10) {
                $job->delete();
                $error = ['jobName' => $job->getName(), 'code' => $code, 'exception' => $res];
                throw new Exception('执行次数超限:' . json_encode($error));
            } else {
                $job->release();
                return false;
            }
        } catch (Exception $e) {
            $job->delete();
            Log::error($e->getMessage());
            return false;
        }
    }

    /**
     * 新增后刷新父区划的子级数量
     * @author 贺强
     * @time   2023/4/25 9:15
     * @param Job $job 当前任务
     * @param string $code 区划码
     * @return bool
     */
    public function refresh_add_district(Job $job, string $code = '') : bool
    {
        if (empty($code)) {
            $job->delete();
            return false;
        }
        try {
            // 当前区划是否存在
            $district = DistrictModel::getModel(['code' => $code], true, '', 0);
            if (empty($district)) {
                $job->delete();
                $error = ['jobName' => $job->getName(), 'code' => $code];
                throw new Exception('区划不存在:' . json_encode($error));
            }
            $res = $this->refresh_par_item($district);
            if ($res === true) {
                $job->delete();
                return true;
            } elseif ($job->attempts() > 10) {
                $job->delete();
                $error = ['jobName' => $job->getName(), 'code' => $code, 'exception' => $res];
                throw new Exception('执行次数超限:' . json_encode($error));
            } else {
                $job->release();
                return false;
            }
        } catch (Exception $e) {
            $job->delete();
            Log::error($e->getMessage());
            return false;
        }
    }

    /**
     * 删除后刷新父区划的子级数量
     * @author 贺强
     * @time   2023/4/25 10:10
     * @param Job $job 当前任务
     * @param array $district 要删除的区划
     * @return bool
     */
    public function refresh_del_district(Job $job, array $district = []) : bool
    {
        if (empty($district)) {
            $job->delete();
            return false;
        }
        try {
            $res = $this->refresh_del_item($district);
            if ($res === true) {
                $job->delete();
                return true;
            } elseif ($job->attempts() > 10) {
                $job->delete();
                $error = ['jobName' => $job->getName(), 'code' => $district['code']];
                throw new Exception('执行次数超限:' . json_encode($error));
            } else {
                $job->release();
                return false;
            }
        } catch (Exception $e) {
            $job->delete();
            Log::error($e->getMessage());
            return false;
        }
    }

    /**
     * 递归刷新子项
     * @author 贺强
     * @time   2023/4/20 15:03
     * @param array $district 区划数据
     * @return bool|Exception
     */
    public function refresh_sub_item(array $district)
    {
        try {
            $level = intval($district['level']);
            if ($level === 3) {
                $prefix = substr($district['code'], 0, 6);
                $village = DistrictModel::getCount([['code', 'like', "$prefix%"], ['level', '=', 4]]);
                if ($village > 0) {
                    $district['children'] = json_encode(['village' => $village]);
                } else {
                    $district['children'] = null;
                }
            } elseif ($level === 2) {
                $prefix = substr($district['code'], 0, 4);
                $county = DistrictModel::getCount([['code', 'like', "$prefix%"], ['level', '=', 3]]);
                $village = DistrictModel::getCount([['code', 'like', "$prefix%"], ['level', '=', 4]]);
                if ($county > 0) {
                    $children['county'] = $county;
                    if ($village > 0) {
                        $children['village'] = $village;
                    } else {
                        unset($children['village']);
                    }
                    $district['children'] = json_encode($children);
                } else {
                    $district['children'] = null;
                }
            } elseif ($level === 1) {
                $prefix = substr($district['code'], 0, 2);
                $city = DistrictModel::getCount([['code', 'like', "$prefix%"], ['level', '=', 2]]);
                $county = DistrictModel::getCount([['code', 'like', "$prefix%"], ['level', '=', 3]]);
                $village = DistrictModel::getCount([['code', 'like', "$prefix%"], ['level', '=', 4]]);
                if ($city > 0) {
                    $children['city'] = $city;
                    if ($county > 0) {
                        $children['county'] = $county;
                        if ($village > 0) {
                            $children['village'] = $village;
                        } else {
                            unset($children['village']);
                        }
                    } else {
                        unset($children['county']);
                    }
                    $district['children'] = json_encode($children);
                } else {
                    $district['children'] = null;
                }
            }
            DistrictModel::modify($district, ['code' => $district['code']]);
            $list = DistrictModel::getList(['pcode' => $district['code']]);
            if (!empty($list)) {
                foreach ($list as $item) {
                    $this->refresh_sub_item($item);
                }
            }
            return true;
        } catch (Exception $e) {
            Log::error($e->getMessage());
            return $e;
        }
    }

    /**
     * 递归刷新父项
     * @author 贺强
     * @time   2023/4/25 9:22
     * @param array $district 区划数据
     * @return bool|Exception
     */
    public function refresh_par_item(array $district)
    {
        try {
            $level = intval($district['level']);
            if ($level === 4) {
                $m3 = DistrictModel::getModel(['code' => $district['pcode']]);
                $c3 = !empty($m3['children']) ? json_decode($m3['children'], true) : [];
                $c3['village'] = !empty($c3['village']) ? $c3['village'] + 1 : 1;
                $m3['children'] = json_encode($c3);
                DistrictModel::modify($m3);
                $m2 = DistrictModel::getModel(['code' => $m3['pcode']]);
                $c2 = !empty($m2['children']) ? json_decode($m2['children'], true) : [];
                $c2['village'] = !empty($c2['village']) ? $c2['village'] + 1 : 1;
                $m2['children'] = json_encode($c2);
                DistrictModel::modify($m2);
                $m1 = DistrictModel::getModel(['code' => $m2['pcode']]);
                $c1 = !empty($m1['children']) ? json_decode($m1['children'], true) : [];
                $c1['village'] = !empty($c1['village']) ? $c1['village'] + 1 : 1;
                $m1['children'] = json_encode($c1);
                DistrictModel::modify($m1);
            } elseif ($level === 3) {
                $m2 = DistrictModel::getModel(['code' => $district['pcode']]);
                $c2 = !empty($m2['children']) ? json_decode($m2['children'], true) : [];
                $c2['county'] = !empty($c2['county']) ? $c2['county'] + 1 : 1;
                $m2['children'] = json_encode($c2);
                DistrictModel::modify($m2);
                $m1 = DistrictModel::getModel(['code' => $m2['pcode']]);
                $c1 = !empty($m1['children']) ? json_decode($m1['children'], true) : [];
                $c1['county'] = !empty($c1['county']) ? $c1['county'] + 1 : 1;
                $m1['children'] = json_encode($c1);
                DistrictModel::modify($m1);
            } elseif ($level === 2) {
                $m1 = DistrictModel::getModel(['code' => $district['pcode']]);
                $c1 = !empty($m1['children']) ? json_decode($m1['children'], true) : [];
                $c1['city'] = !empty($c1['city']) ? $c1['city'] + 1 : 1;
                $m1['children'] = json_encode($c1);
                DistrictModel::modify($m1);
            }
            return true;
        } catch (Exception $e) {
            Log::error($e->getMessage());
            return $e;
        }
    }

    /**
     * 递归删除并刷新父级
     * @author 贺强
     * @time   2023/4/25 14:23
     * @param $district
     * @return bool
     */
    public function refresh_del_item($district)
    {
        try {
            $level = intval($district['level']);
            if ($level === 4) {
                $m3 = DistrictModel::getModel(['code' => $district['pcode']]);
                $c3 = !empty($m3['children']) ? json_decode($m3['children'], true) : [];
                if ($c3['village'] > 1) {
                    $c3['village'] -= 1;
                } else {
                    $c3 = null;
                }
                if (!empty($c3)) {
                    $c3 = json_encode($c3);
                }
                $m3['children'] = $c3;
                DistrictModel::modify($m3);
                $m2 = DistrictModel::getModel(['code' => $m3['pcode']]);
                $c2 = !empty($m2['children']) ? json_decode($m2['children'], true) : [];
                if ($c2['village'] > 1) {
                    $c2['village'] -= 1;
                } else {
                    unset($c2['village']);
                    if (empty($c2)) {
                        $c2 = null;
                    }
                }
                if (!empty($c2)) {
                    $c2 = json_encode($c2);
                }
                $m2['children'] = $c2;
                DistrictModel::modify($m2);
                $m1 = DistrictModel::getModel(['code' => $m2['pcode']]);
                $c1 = !empty($m1['children']) ? json_decode($m1['children'], true) : [];
                if ($c1['village'] > 1) {
                    $c1['village'] -= 1;
                } else {
                    unset($c1['village']);
                    if (empty($c1)) {
                        $c1 = null;
                    }
                }
                if (!empty($c1)) {
                    $c1 = json_encode($c1);
                }
                $m1['children'] = $c1;
                DistrictModel::modify($m1);
                DistrictModel::delById($district['id']);
            } elseif ($level === 3) {
                $village_where = ['pcode' => $district['code']];
                // 查询被删除区划子级数量
                $village = DistrictModel::getCount($village_where);
                if ($village > 0) {
                    // 删除被删除区划子级区划
                    DistrictModel::delByWhere($village_where);
                }
                // 获取被删除的区划父级区划，并更新父级所拥有的子级数量
                $m2 = DistrictModel::getModel(['code' => $district['pcode']]);
                $c2 = !empty($m2['children']) ? json_decode($m2['children'], true) : [];
                if ($village > 0 && !empty($c2['village'])) {
                    // 更新第 2 级的 4 级子区划数量
                    $c2['village'] -= $village;
                    if ($c2['village'] < 1) {
                        unset($c2['village']);
                    }
                }
                // 更新第 2 级的 3 级子区划数量
                if ($c2['county'] > 1) {
                    $c2['county'] -= 1;
                } else {
                    unset($c2['county']);
                    if (empty($c2)) {
                        $c2 = null;
                    }
                }
                if (!empty($c2)) {
                    $c2 = json_encode($c2);
                }
                $m2['children'] = $c2;
                DistrictModel::modify($m2);
                // 获取被删除的区划的 1 级区划
                $m1 = DistrictModel::getModel(['code' => $m2['pcode']]);
                $c1 = !empty($m1['children']) ? json_decode($m1['children'], true) : [];
                if ($village > 0 && !empty($c1['village'])) {
                    // 更新第 1 级的 4 级子区划数量
                    $c1['village'] -= $village;
                    if ($c1['village'] < 1) {
                        unset($c1['village']);
                    }
                }
                // 更新第 1 级的 3 级子区划数量
                if ($c1['county'] > 1) {
                    $c1['county'] -= 1;
                } else {
                    unset($c1['county']);
                    if (empty($c1)) {
                        $c1 = null;
                    }
                }
                if (!empty($c1)) {
                    $c1 = json_encode($c1);
                }
                $m1['children'] = $c1;
                DistrictModel::modify($m1);
                DistrictModel::delById($district['id']);
            } elseif ($level === 2) {
                // 查询被删除区划 4 级数量
                $code = substr($district['code'], 0, 4);
                $village_where = [['pcode', 'like', "$code%"], ['level', '=', 4]];
                $village = DistrictModel::getCount($village_where);
                if ($village > 0) {
                    // 删除被删除区划 4 级区划
                    DistrictModel::delByWhere($village_where);
                }
                // 查询被删除区划子级数量
                $county_where = ['pcode' => $district['code']];
                $county = DistrictModel::getCount($county_where);
                if ($county > 0) {
                    // 删除被删除区划子级区划
                    DistrictModel::delByWhere($county_where);
                }
                // 获取被删除区划的父级区划
                $m1 = DistrictModel::getModel(['code' => $district['pcode']]);
                $c1 = !empty($m1['children']) ? json_decode($m1['children'], true) : [];
                if ($village > 0 && !empty($c1['village'])) {
                    // 更新第 1 级的 4 级子区划数量
                    $c1['village'] -= $village;
                    if ($c1['village'] < 1) {
                        unset($c1['village']);
                    }
                }
                if ($county > 0 && !empty($c1['county'])) {
                    // 更新第 1 级的 3 级子区划数量
                    $c1['county'] -= $county;
                    if ($c1['county'] < 1) {
                        unset($c1['county']);
                    }
                }
                // 更新 1 级的 2 级子区划数量
                if ($c1['city'] > 1) {
                    $c1['city'] -= 1;
                } else {
                    unset($c1['city']);
                    if (empty($c1)) {
                        $c1 = null;
                    }
                }
                if (!empty($c1)) {
                    $c1 = json_encode($c1);
                }
                $m1['children'] = $c1;
                DistrictModel::modify($m1);
                DistrictModel::delById($district['id']);
            } elseif ($level === 1) {
                $code = substr($district['code'], 0, 2);
                DistrictModel::delByWhere([['code', 'like', "$code%"]]);
            }
            return true;
        } catch (Exception $e) {
            Log::error($e->getMessage());
            return false;
        }
    }
}
